package daemon

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"go.uber.org/zap"
)

// FileUtils 文件操作工具
type FileUtils struct{}

// NewFileUtils 创建文件操作工具
func NewFileUtils() *FileUtils {
	return &FileUtils{}
}

// CreatePIDFile 创建PID文件
func (fu *FileUtils) CreatePIDFile(pidFile string) error {
	pid := os.Getpid()
	pidContent := fmt.Sprintf("%d", pid)

	// 确保目录存在
	dir := filepath.Dir(pidFile)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建PID目录失败: %v", err)
	}

	// 写入PID文件
	if err := os.WriteFile(pidFile, []byte(pidContent), 0644); err != nil {
		return fmt.Errorf("写入PID文件失败: %v", err)
	}

	zap.L().Info("PID文件创建成功", zap.String("pidFile", pidFile), zap.Int("pid", pid))
	return nil
}

// RemovePIDFile 删除PID文件
func (fu *FileUtils) RemovePIDFile(pidFile string) error {
	if _, err := os.Stat(pidFile); err == nil {
		if err := os.Remove(pidFile); err != nil {
			return err
		}
		zap.L().Info("PID文件删除成功", zap.String("pidFile", pidFile))
	}
	return nil
}

// IsProcessRunning 检查进程是否在运行
func (fu *FileUtils) IsProcessRunning(pidFile string) bool {
	if _, err := os.Stat(pidFile); err != nil {
		return false
	}

	// 读取PID文件
	content, err := os.ReadFile(pidFile)
	if err != nil {
		return false
	}

	// 检查进程是否存在
	var pid int
	fmt.Sscanf(string(content), "%d", &pid)
	if pid <= 0 {
		return false
	}

	// 检查进程是否存活
	process, err := os.FindProcess(pid)
	if err != nil {
		return false
	}

	// 发送信号0检查进程状态
	return process.Signal(syscall.Signal(0)) == nil
}

// WriteLogEntry 写入日志条目
func (fu *FileUtils) WriteLogEntry(logFile, entry string) error {
	// 确保目录存在
	dir := filepath.Dir(logFile)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("创建日志目录失败: %v", err)
	}

	// 打开或创建日志文件
	f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return fmt.Errorf("打开日志文件失败: %v", err)
	}
	defer f.Close()

	// 写入日志条目
	if _, err := f.WriteString(entry + "\n"); err != nil {
		return fmt.Errorf("写入日志文件失败: %v", err)
	}

	return nil
}

// ReadPIDFromFile 从PID文件读取进程ID
func (fu *FileUtils) ReadPIDFromFile(pidFile string) (int, error) {
	content, err := os.ReadFile(pidFile)
	if err != nil {
		return 0, fmt.Errorf("读取PID文件失败: %v", err)
	}

	var pid int
	if _, err := fmt.Sscanf(string(content), "%d", &pid); err != nil {
		return 0, fmt.Errorf("解析PID失败: %v", err)
	}

	return pid, nil
}

// FileExists 检查文件是否存在
func (fu *FileUtils) FileExists(filePath string) bool {
	_, err := os.Stat(filePath)
	return err == nil
}

// EnsureDirectory 确保目录存在
func (fu *FileUtils) EnsureDirectory(dirPath string) error {
	return os.MkdirAll(dirPath, 0755)
}

// CopyFile 复制文件
func (fu *FileUtils) CopyFile(src, dst string) error {
	// 打开源文件
	source, err := os.Open(src)
	if err != nil {
		return err
	}
	defer source.Close()

	// 创建目标文件
	destination, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer destination.Close()

	// 复制文件内容
	_, err = io.Copy(destination, source)
	return err
}

// GetFileSize 获取文件大小
func (fu *FileUtils) GetFileSize(filePath string) (int64, error) {
	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return 0, err
	}
	return fileInfo.Size(), nil
}

// CleanupOldFiles 清理旧文件
func (fu *FileUtils) CleanupOldFiles(dirPath string, maxAge time.Duration) error {
	files, err := os.ReadDir(dirPath)
	if err != nil {
		return err
	}

	now := time.Now()
	for _, file := range files {
		if file.IsDir() {
			continue
		}

		filePath := filepath.Join(dirPath, file.Name())
		fileInfo, err := file.Info()
		if err != nil {
			continue
		}

		if now.Sub(fileInfo.ModTime()) > maxAge {
			if err := os.Remove(filePath); err != nil {
				zap.L().Warn("删除旧文件失败", zap.String("filePath", filePath), zap.Error(err))
			} else {
				zap.L().Info("已删除旧文件", zap.String("filePath", filePath))
			}
		}
	}

	return nil
}